require('module-alias/register')

const express = require('express')
const fileUpload = require('express-fileupload')
const { expressjwt } = require('express-jwt')
const cookieParser = require('cookie-parser')
const session = require('express-session')
const { secretKey } = require('./config')
const logger = require('morgan')
const dayjs = require('dayjs')
// const cors = require('cors')
const cors = require('./middleware/cors')
const path = require('path')
const joi = require('joi')

const app = express()

app.use(cookieParser('pudding-api'))
app.use(session({
  secret: 'pudding-api',
  name: 'pudding-captcha',
  resave: false,
  saveUninitialized: true,
  cookie: { maxAge: 1000 * 60 * 100, httpOnly: false },
  rolling: true,
}))

// 上传
app.use(fileUpload({
  createParentPath: true,
  limits: {
    fileSize: 2 * 1024 * 1024 * 1024, // 文件总大小上限2MB
  },
}))

app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use('/public', express.static(path.join(__dirname, 'public')))
// app.use(cors())

app.all('*', cors)


// 一定要在路由之前，封装 res.cc 函数
app.use((req, res, next) => {
  // status 默认值为 1，表示失败的情况
  // err 的值，可能是一个错误对象，也可能是一个错误的描述字符串
  req.body.update_time = dayjs().format('YYYY-MM-DD HH:mm:ss')

  res.cc = function(err, code = 1, rest) {
    const message = err instanceof Error ? err.message : err

    return res.send({ code, message, ...rest })
  }
  next()
})

// 注意：只要配置成功了 express-jwt 这个中间件，就可以把解析出来的用户信息，挂载到 `req.user` 属性上
const publicPaths = [
  { url: /^\/api\/web\/.*/, methods: ['GET', 'POST'] },
  { url: /^\/public\/.*/, methods: ['GET'] },
]
const webPaths = [
  '/api/pro/user/register',
  '/api/pro/user/login',
]
const jwtMiddleware = expressjwt({ secret: secretKey, algorithms: ['HS256'] })

app.use(jwtMiddleware.unless({
  path: [...publicPaths, ...webPaths],
}))

app.use((err, req, res, next) => {
  // 这次错误是由 token 解析失败导致的
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '无效的token',
    })
  }

  return res.send({
    status: 500,
    message: '未知的错误',
  })
})

const Router = require('./routers')

app.use('/', Router)


// 错误级别中间件
app.use(function(err, req, res, next) {
  // express-joi：Joi 参数校验失败
  if (err instanceof joi.ValidationError) {
    return res.cc(err, 2)
  }

  // 2、express-jwt：捕获身份认证失败的错误
  if (err.name === 'UnauthorizedError') {
    return res.cc('身份认证失败！')
  }

  // 其他未知错误
  return res.cc(err)
})

app.listen('9001', function() {
  console.log('api server running at http://localhost:9001')
})

module.exports = app
